﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Linq;
using System.Collections.Generic;
using QSHC.QSchedule.Web.Models;
using QSHC.QSchedule.Web.Services;

namespace QSHC.QSchedule.Silverlight.Helpers
{
    public class CalendarHelper
    {
        public static IEnumerable<Holiday> _holidays;
        public static IEnumerable<PhysicianAbsent> _physicianAbsent;
        public static IEnumerable<PhysicianSchedule> _physicianSchedules;

        public static void LoadHolidaysAndSchedules()
        {
            var client = new QScheduleDomainContext();

            var lo = client.Load(client.GetHolidaysQuery());
            lo.Completed += (s, e) =>
            {
                _holidays = lo.Entities;
            };

            var lo2 = client.Load(client.GetPhysicianSchedulesQuery());
            lo2.Completed += (s, e) =>
            {
                _physicianSchedules = lo2.Entities;
            };

            var lo3 = client.Load(client.GetPhysicianAbsentsQuery());
            lo3.Completed += (s, e) =>
                {
                    _physicianAbsent = lo3.Entities;
                };
        }

        public static IEnumerable<DateTime> GetBlackoutDates(Service service, Employee physician, DateTime displayDate)
        {
            var firstDayOfMonth = new DateTime(displayDate.Year, displayDate.Month, 1);
            var firstDateToDisplay = firstDayOfMonth.AddDays(-(int)firstDayOfMonth.DayOfWeek + 1);
            if (firstDayOfMonth.DayOfWeek == DayOfWeek.Sunday || firstDayOfMonth.DayOfWeek == DayOfWeek.Monday)
                firstDateToDisplay = firstDateToDisplay.AddDays(-7);

            var lastDateToDisplay = firstDateToDisplay.AddDays(41);

            if (service == null || physician == null)
            {
                var blackout = new List<DateTime>();
                for (int i = 0; i < 42; i++)
                {
                    blackout.Add(firstDateToDisplay.AddDays(i));
                }
                return blackout;
            }
            else
            {
                // Holidays
                var holidays = _holidays.Where(p => p.HolidayDate >= firstDateToDisplay && p.HolidayDate <= lastDateToDisplay).Select(p => p.HolidayDate);

                // Physician Absents
                var physicianAbsents = _physicianAbsent.Where(p => p.Physician == physician.EmployeeCode
                                                                    && (p.ServiceID != null ? p.ServiceID == service.ServiceID : true) &&
                                                                    ((p.BeginDate <= lastDateToDisplay && p.BeginDate >= firstDateToDisplay) ||
                                                                    (p.EndDate != null ?
                                                                    (p.EndDate >= firstDateToDisplay && p.EndDate <= lastDateToDisplay) : true)));

                var absentDates = new List<DateTime>();
                foreach (var absent in physicianAbsents)
                {
                    int i = 0;
                    var firstDate = absent.BeginDate <= firstDateToDisplay ? firstDateToDisplay : absent.BeginDate;

                    while (true)
                    {
                        var absentDate = firstDate.AddDays(i);
                        if (absentDate <= lastDateToDisplay && (absent.EndDate != null ? absentDate <= absent.EndDate.Value : true))
                            absentDates.Add(absentDate);
                        else
                            break;

                        i++;
                    }
                }

                // Physician Schedules
                var physicianSchedules = _physicianSchedules.Where(p => p.ServiceID == service.ServiceID &&
                                                                        p.Physician == physician.EmployeeCode &&
                                                                        ((p.BeginDate <= lastDateToDisplay && p.BeginDate >= firstDateToDisplay) ||
                                                                        (p.EndDate != null ?
                                                                        (p.EndDate >= firstDateToDisplay && (p.EndDate >= lastDateToDisplay ? true : p.EndDate == p.EndDate)) : true)));

                var scheduleDates = new List<DateTime>();
                foreach (var schedule in physicianSchedules)
                {
                    int i = 0;
                    var firstDate = schedule.BeginDate <= firstDateToDisplay ? firstDateToDisplay : schedule.BeginDate;

                    while (true)
                    {
                        var scheduleDate = firstDate.AddDays(i);
                        if (scheduleDate <= lastDateToDisplay &&
                            (schedule.EndDate != null ? scheduleDate <= schedule.EndDate.Value : true))
                        {
                            var aa = (int)scheduleDate.DayOfWeek;

                            if ((int)scheduleDate.DayOfWeek == schedule.DayOfWeek)
                                scheduleDates.Add(scheduleDate);
                        }
                        else
                            break;

                        i++;
                    }
                }

                var blackoutDates = new List<DateTime>();
                int j = 0;

                if (service.ServiceID == 10)  //ถ้าเป็นนัดนอนโรงพยาบาลไม่ต้องเอา Holiday มาคิด
                {
                    while (true)
                    {
                        var blackoutDate = firstDateToDisplay.AddDays(j);

                        if (!(!absentDates.Contains(blackoutDate) && scheduleDates.Contains(blackoutDate)))
                            blackoutDates.Add(blackoutDate);

                        if (blackoutDate == lastDateToDisplay)
                            break;

                        j++;
                    }
                }
                else
                {
                    while (true)
                    {
                        var blackoutDate = firstDateToDisplay.AddDays(j);

                        if (!(!absentDates.Contains(blackoutDate) && !holidays.Contains(blackoutDate) && scheduleDates.Contains(blackoutDate)))
                            blackoutDates.Add(blackoutDate);

                        if (blackoutDate == lastDateToDisplay)
                            break;

                        j++;
                    }
                }

                return blackoutDates;

            }

        }

        public static bool IsAvailableDate(DateTime date, Service service, Employee physician)
        {
            if (_holidays.Where(p => p.HolidayDate == date).Count() > 0)
                return false;

            if (_physicianAbsent.Where(p => p.Physician == physician.EmployeeCode && 
                                            (p.ServiceID != null ? p.ServiceID == service.ServiceID : true) &&
                                            (p.BeginDate <= date && (p.EndDate != null ? p.EndDate >= date : true)))
                                .Count() > 0)
                return false;

            if (_physicianSchedules.Where(p => p.ServiceID == service.ServiceID &&
                                               p.Physician == physician.EmployeeCode &&
                                               (p.BeginDate <= date && (p.EndDate != null ? p.EndDate >= date : true)) &&
                                               p.DayOfWeek == (int)date.DayOfWeek)
                                .Count() == 0)
                return false;

            return true;
        }
    }
}
